Popular Searches
Popular Course Categories
Popular Courses

Base Test

Page Object Model

Base Test in Selenium TestNG

Base Test is a reusable parent class used in Selenium automation frameworks to centralize common test setup and cleanup operations. Instead of creating WebDriver initialization, browser configuration, URL navigation, and browser closing logic in every test class, these common operations can be placed inside a BaseTest class.

Test classes can then extend the BaseTest class and directly use the initialized WebDriver. This reduces duplicate code, improves maintainability, and provides a consistent test execution structure. A BaseTest class is commonly combined with TestNG lifecycle annotations such as @BeforeMethod, @AfterMethod, @BeforeClass, and @AfterClass. :contentReference[oaicite:0]{index=0}

In a Selenium framework, the BaseTest generally acts as the common foundation between the test classes, WebDriver management, Page Object Model, configuration, reporting, screenshots, and other reusable framework components.

Course Resource: Selenium Training | Register for Course Demo


1. What is a Base Test?

A BaseTest is a parent or superclass that contains common functionality required by multiple automated test classes.

For example, if an automation project contains 50 test classes and every test requires a browser to be opened before execution and closed after execution, placing this logic in every test class would create unnecessary duplication.

Instead, the common browser lifecycle can be implemented once in BaseTest.

BaseTest

   |

   +-- WebDriver initialization

   |

   +-- Browser configuration

   |

   +-- Application URL

   |

   +-- Common setup

   |

   +-- Common cleanup

   |

   +-- Screenshot handling

   |

   +-- Configuration

   |

   +-- Logging / Reporting

   |

   +-- Test Classes


2. Why is Base Test Important?

BaseTest is important because it provides a centralized location for common automation functionality.

  • Reduces duplicate setup and teardown code.
  • Provides reusable WebDriver management.
  • Improves test class readability.
  • Creates a consistent test lifecycle.
  • Makes framework maintenance easier.
  • Supports Page Object Model architecture.
  • Can centralize browser configuration.
  • Can integrate configuration files.
  • Can support screenshots and reporting.
  • Can support multiple browsers.
  • Can be extended for parallel execution.
  • Can simplify CI/CD execution.


3. Base Test and Test Classes

The basic relationship between BaseTest and test classes is inheritance.

BaseTest

   |

   |-- LoginTest

   |

   |-- SearchTest

   |

   |-- RegistrationTest

   |

   |-- CheckoutTest

   |

   |-- ProfileTest

Each test class extends BaseTest and inherits the common functionality.

public class LoginTest extends BaseTest {

}

 

public class SearchTest extends BaseTest {

}

 

public class CheckoutTest extends BaseTest {

}


4. Basic Base Test Example

A simple BaseTest can initialize Chrome before every test method and close the browser after the test completes.

import org.openqa.selenium.WebDriver;

import org.openqa.selenium.chrome.ChromeDriver;

import org.testng.annotations.AfterMethod;

import org.testng.annotations.BeforeMethod;

 

public class BaseTest {

 

    protected WebDriver driver;

 

    @BeforeMethod

    public void setUp() {

        driver = new ChromeDriver();

        driver.manage().window().maximize();

    }

 

    @AfterMethod

    public void tearDown() {

        if (driver != null) {

            driver.quit();

        }

    }

}

The protected WebDriver allows child test classes to access the driver while keeping the field hidden from unrelated classes.


5. Understanding @BeforeMethod

@BeforeMethod is a TestNG configuration annotation that runs before each test method. It is commonly used in BaseTest to create a fresh browser session for every test.

@BeforeMethod

public void setUp() {

    driver = new ChromeDriver();

}

For example, if a class contains three test methods:

@Test

public void testLogin() {

}

 

@Test

public void testSearch() {

}

 

@Test

public void testCheckout() {

}

The conceptual execution is:

setUp()

   |

testLogin()

   |

tearDown()

 

setUp()

   |

testSearch()

   |

tearDown()

 

setUp()

   |

testCheckout()

   |

tearDown()


6. Understanding @AfterMethod

@AfterMethod executes after each TestNG test method. It is commonly used to close the browser and release WebDriver resources.

@AfterMethod

public void tearDown() {

    if (driver != null) {

        driver.quit();

    }

}

Using driver.quit() closes the browser session and associated browser windows.


7. Why Use protected WebDriver?

In a BaseTest class, WebDriver is commonly declared as protected.

protected WebDriver driver;

This allows classes that extend BaseTest to access the driver directly.

public class LoginTest extends BaseTest {

 

    @Test

    public void loginTest() {

        driver.get("https://example.com/login");

    }

}

The test does not need to create another WebDriver instance because it inherits the driver from BaseTest.


8. Base Test with Application URL

The BaseTest can also navigate to the application URL during setup.

import org.openqa.selenium.WebDriver;

import org.openqa.selenium.chrome.ChromeDriver;

import org.testng.annotations.AfterMethod;

import org.testng.annotations.BeforeMethod;

 

public class BaseTest {

 

    protected WebDriver driver;

 

    @BeforeMethod

    public void setUp() {

        driver = new ChromeDriver();

        driver.manage().window().maximize();

        driver.get("https://example.com");

    }

 

    @AfterMethod

    public void tearDown() {

        if (driver != null) {

            driver.quit();

        }

    }

}

Every test that extends BaseTest will start with the application already opened.


9. Base Test with Login Test

A test class can extend BaseTest and focus only on the actual test scenario.

import org.testng.Assert;

import org.testng.annotations.Test;

 

public class LoginTest extends BaseTest {

 

    @Test

    public void verifyLoginPage() {

        driver.get("https://example.com/login");

 

        String title = driver.getTitle();

 

        Assert.assertTrue(

            title.contains("Login")

        );

    }

}

The browser setup and cleanup remain inside BaseTest while the test class contains the validation logic.


10. Base Test with Multiple Test Classes

A single BaseTest can be reused by many test classes.

public class LoginTest extends BaseTest {

 

    @Test

    public void loginTest() {

        driver.get("https://example.com/login");

    }

}

public class SearchTest extends BaseTest {

 

    @Test

    public void searchTest() {

        driver.get("https://example.com/search");

    }

}

public class CheckoutTest extends BaseTest {

 

    @Test

    public void checkoutTest() {

        driver.get("https://example.com/checkout");

    }

}

This approach keeps browser lifecycle management centralized.


11. Base Test Execution Flow

TestNG starts

     |

     v

Test class extends BaseTest

     |

     v

@BeforeMethod

     |

     v

Create WebDriver

     |

     v

Configure browser

     |

     v

Open application

     |

     v

@Test method

     |

     v

Assertions

     |

     v

@AfterMethod

     |

     v

driver.quit()

     |

     v

Test completed


12. Base Test with Browser Configuration

A BaseTest can centralize browser configuration such as window size, browser options, and other common WebDriver settings.

@BeforeMethod

public void setUp() {

 

    driver = new ChromeDriver();

 

    driver.manage().window().maximize();

 

    driver.manage().deleteAllCookies();

}

Centralizing these settings prevents each test class from implementing the same browser configuration.


13. Base Test with ChromeOptions

ChromeOptions can be configured in BaseTest when browser-specific settings are required.

import org.openqa.selenium.chrome.ChromeDriver;

import org.openqa.selenium.chrome.ChromeOptions;

 

@BeforeMethod

public void setUp() {

 

    ChromeOptions options = new ChromeOptions();

 

    options.addArguments("--start-maximized");

 

    driver = new ChromeDriver(options);

}

Common options can be maintained centrally and reused by all test classes.


14. Base Test with Firefox

The BaseTest can also be designed for Firefox.

import org.openqa.selenium.firefox.FirefoxDriver;

 

@BeforeMethod

public void setUp() {

    driver = new FirefoxDriver();

    driver.manage().window().maximize();

}

For multi-browser frameworks, the browser creation logic is usually moved into a DriverFactory rather than placing every browser implementation directly inside BaseTest.


15. Base Test with Browser Parameter

TestNG parameters can be used to select a browser dynamically.

@Parameters("browser")

@BeforeMethod

public void setUp(String browser) {

 

    if (browser.equalsIgnoreCase("chrome")) {

        driver = new ChromeDriver();

    } else if (browser.equalsIgnoreCase("firefox")) {

        driver = new FirefoxDriver();

    } else {

        throw new IllegalArgumentException(

            "Unsupported browser: " + browser

        );

    }

}

This allows the same test framework to execute against different browsers without changing the test classes.


16. Base Test with @Optional

The @Optional annotation can provide a default value when a TestNG parameter is not supplied.

@Parameters("browser")

@BeforeMethod

public void setUp(

        @Optional("chrome") String browser) {

 

    if (browser.equalsIgnoreCase("chrome")) {

        driver = new ChromeDriver();

    } else if (browser.equalsIgnoreCase("firefox")) {

        driver = new FirefoxDriver();

    }

}

This can make local execution easier when no browser parameter is supplied through TestNG XML.


17. Base Test with testng.xml

A browser parameter can be supplied through a TestNG XML suite.

<suite name="Automation Suite">

    <test name="Chrome Tests">

        <parameter name="browser" value="chrome"/>

        <classes>

            <class name="tests.LoginTest"/>

        </classes>

    </test>

</suite>

The BaseTest reads the parameter and creates the appropriate WebDriver.


18. Base Test with Configuration File

For larger projects, browser and application settings can be maintained in a configuration file instead of being hard-coded inside BaseTest.

browser=chrome

baseUrl=https://example.com

headless=false

A ConfigReader utility can read these values and BaseTest can use them during setup.


19. Base Test with ConfigReader

public class ConfigReader {

 

    public static String getBrowser() {

        return "chrome";

    }

 

    public static String getBaseUrl() {

        return "https://example.com";

    }

}

BaseTest can consume these configuration values.

@BeforeMethod

public void setUp() {

 

    String browser = ConfigReader.getBrowser();

 

    if (browser.equalsIgnoreCase("chrome")) {

        driver = new ChromeDriver();

    }

 

    driver.manage().window().maximize();

    driver.get(ConfigReader.getBaseUrl());

}


20. Base Test and Page Object Model

BaseTest works closely with the Page Object Model. BaseTest manages the WebDriver lifecycle, while page classes manage page-specific locators and actions. :contentReference[oaicite:1]{index=1}

BaseTest

    |

    +-- WebDriver

    |

    +-- Setup / Teardown

    |

    +-- LoginTest

            |

            +-- LoginPage

                    |

                    +-- Locators

                    +-- Actions

This separation makes the framework easier to understand and maintain.


21. Base Test with Page Object Example

public class LoginPage {

 

    private WebDriver driver;

 

    private By username =

        By.id("username");

 

    private By password =

        By.id("password");

 

    private By loginButton =

        By.id("loginButton");

 

    public LoginPage(WebDriver driver) {

        this.driver = driver;

    }

 

    public void login(

            String user,

            String pass) {

 

        driver.findElement(username)

              .sendKeys(user);

 

        driver.findElement(password)

              .sendKeys(pass);

 

        driver.findElement(loginButton)

              .click();

    }

}

The test class can use the WebDriver inherited from BaseTest.

public class LoginTest extends BaseTest {

 

    @Test

    public void validLoginTest() {

 

        LoginPage loginPage =

            new LoginPage(driver);

 

        loginPage.login(

            "testuser",

            "password"

        );

    }

}


22. Base Test and Assertions

BaseTest should generally manage the test environment, while assertions should remain in the test or appropriate validation layer.

@Test

public void verifyTitle() {

 

    driver.get("https://example.com");

 

    String actualTitle =

        driver.getTitle();

 

    Assert.assertEquals(

        actualTitle,

        "Example Domain"

    );

}

This separation prevents BaseTest from becoming overloaded with application-specific validations.


23. Base Test and Test Data

Test data should normally remain separate from BaseTest. Data Providers, Excel files, JSON files, databases, or configuration utilities can supply test data.

BaseTest

    |

    +-- Browser Lifecycle

 

DataProvider

    |

    +-- Test Data

 

Test Class

    |

    +-- Test Scenario

 

Page Object

    |

    +-- Page Actions


24. Base Test with DataProvider

BaseTest can be combined with TestNG DataProvider for data-driven Selenium testing.

public class LoginTest extends BaseTest {

 

    @DataProvider(name = "loginData")

    public Object[][] loginData() {

        return new Object[][] {

            {"admin", "admin123"},

            {"manager", "manager123"},

            {"employee", "employee123"}

        };

    }

 

    @Test(dataProvider = "loginData")

    public void loginTest(

            String username,

            String password) {

 

        driver.get(

            "https://example.com/login"

        );

 

        System.out.println(username);

    }

}


25. Base Test with Screenshots

BaseTest or a TestNG listener can participate in screenshot handling when a test fails.

public void takeScreenshot(String testName) {

 

    TakesScreenshot screenshot =

        (TakesScreenshot) driver;

 

    File source =

        screenshot.getScreenshotAs(

            OutputType.FILE

        );

 

    // Save the screenshot to the

    // framework's screenshot directory.

}

In larger frameworks, screenshot capture is often implemented through a TestNG listener so that failure handling remains separate from the basic browser lifecycle.


26. Base Test and TestNG Listener

Listeners can monitor test execution events such as test start, success, failure, and skipped tests. BaseTest can expose the WebDriver needed by a listener for screenshot capture.

BaseTest

    |

    +-- WebDriver

    |

    +-- Test Lifecycle

             |

             v

        TestNG Listener

             |

       +-----+-----+

       |           |

    Success      Failure

                   |

                   v

              Screenshot

                   |

                   v

                 Report


27. Base Test and Reporting

A reusable BaseTest can be integrated with reporting utilities. The test lifecycle can provide information needed by reporting components.

Test Execution

      |

      v

BaseTest

      |

      v

Test Method

      |

      v

Pass / Fail

      |

      v

Listener

      |

      v

Report

For production frameworks, reporting is generally handled by dedicated listeners or reporting utilities rather than putting extensive reporting code directly inside BaseTest.


28. Base Test with Explicit Wait

Wait management can be centralized through a utility or helper rather than creating waits repeatedly inside test classes.

public WebDriverWait getWait() {

 

    return new WebDriverWait(

        driver,

        Duration.ofSeconds(10)

    );

}

A test or Page Object can use the common wait configuration.


29. Base Test and Utility Classes

A scalable automation framework should avoid putting every framework feature into BaseTest. Instead, BaseTest should coordinate reusable components.

BaseTest

   |

   +-- DriverFactory

   |

   +-- ConfigReader

   |

   +-- WaitUtils

   |

   +-- ScreenshotUtils

   |

   +-- Logger

   |

   +-- Test Listener

   |

   +-- Page Objects

   |

   +-- Test Classes

This keeps BaseTest focused and prevents it from becoming a large class containing unrelated responsibilities.


30. Base Test vs Driver Factory

BaseTestDriverFactory
Manages test lifecycleCreates WebDriver instances
Runs setup and teardownContains browser creation logic
Provides driver to testsCan support multiple browsers
Coordinates framework setupFocuses on driver creation

Separating these responsibilities is useful as the automation framework becomes larger.


31. Using DriverFactory with BaseTest

public class DriverFactory {

 

    public static WebDriver createDriver(

            String browser) {

 

        if (browser.equalsIgnoreCase("chrome")) {

            return new ChromeDriver();

        }

 

        if (browser.equalsIgnoreCase("firefox")) {

            return new FirefoxDriver();

        }

 

        throw new IllegalArgumentException(

            "Unsupported browser: " + browser

        );

    }

}

BaseTest can then use the factory.

public class BaseTest {

 

    protected WebDriver driver;

 

    @BeforeMethod

    public void setUp() {

 

        driver =

            DriverFactory.createDriver("chrome");

 

        driver.manage().window().maximize();

    }

 

    @AfterMethod

    public void tearDown() {

 

        if (driver != null) {

            driver.quit();

        }

    }

}


32. Base Test with Multiple Browsers

A browser-independent framework can use a browser parameter and DriverFactory together.

@Parameters("browser")

@BeforeMethod

public void setUp(

        @Optional("chrome") String browser) {

 

    driver =

        DriverFactory.createDriver(browser);

 

    driver.manage().window().maximize();

}

This design keeps browser-specific creation logic outside the BaseTest.


33. Base Test with Parallel Execution

When tests execute in parallel, a shared WebDriver instance can cause test interference. A common approach is to associate a separate WebDriver instance with each execution thread.

Parallel Test Execution

 

Thread 1

   |

   +-- WebDriver 1

   |

   +-- LoginTest

 

Thread 2

   |

   +-- WebDriver 2

   |

   +-- SearchTest

 

Thread 3

   |

   +-- WebDriver 3

   |

   +-- CheckoutTest

For parallel frameworks, ThreadLocal<WebDriver> is commonly used to isolate driver instances between threads. :contentReference[oaicite:2]{index=2}


34. ThreadLocal WebDriver in Base Test

public class BaseTest {

 

    private static final

    ThreadLocal<WebDriver> driver =

        new ThreadLocal<>();

 

    @BeforeMethod

    public void setUp() {

 

        driver.set(new ChromeDriver());

 

        getDriver()

            .manage()

            .window()

            .maximize();

    }

 

    protected WebDriver getDriver() {

        return driver.get();

    }

 

    @AfterMethod

    public void tearDown() {

 

        if (getDriver() != null) {

            getDriver().quit();

            driver.remove();

        }

    }

}

The important idea is that each thread gets its own WebDriver instance rather than sharing one browser session.


35. Why ThreadLocal is Useful

Shared DriverThreadLocal Driver
Multiple tests may use the same browserEach thread can have its own browser
Can cause test interferenceProvides thread isolation
Difficult for parallel executionBetter suited to parallel execution
Risk of race conditionsReduces shared-driver conflicts


36. Base Test with Headless Browser

BaseTest can configure headless execution when browser UI is not required.

ChromeOptions options =

    new ChromeOptions();

 

options.addArguments("--headless=new");

 

driver = new ChromeDriver(options);

Headless execution can be useful in CI/CD environments, provided the application and tests behave correctly in headless mode.


37. Base Test and Environment Configuration

A BaseTest can initialize different environments such as QA, staging, and other test environments.

environment=qa

baseUrl=https://qa.example.com

The framework can load the appropriate URL before each test.

driver.get(ConfigReader.getBaseUrl());


38. Base Test with Environment Parameter

@Parameters("environment")

@BeforeMethod

public void setUp(

        @Optional("qa") String environment) {

 

    String url;

 

    if (environment.equalsIgnoreCase("qa")) {

        url = "https://qa.example.com";

    } else if (

        environment.equalsIgnoreCase("stage")) {

        url = "https://stage.example.com";

    } else {

        throw new IllegalArgumentException(

            "Unsupported environment: " + environment

        );

    }

 

    driver = new ChromeDriver();

    driver.manage().window().maximize();

    driver.get(url);

}


39. Base Test and Browser Cleanup

Browser cleanup is one of the most important responsibilities of a BaseTest.

@AfterMethod(alwaysRun = true)

public void tearDown() {

 

    if (driver != null) {

        driver.quit();

    }

}

Using alwaysRun = true can help ensure cleanup is attempted even when test setup or execution encounters a failure.


40. Base Test and Test Independence

A good BaseTest should help maintain test independence. A test should not depend on the browser state left behind by another test.

Test 1

  |

  +-- New Browser

  +-- Execute

  +-- Close Browser

 

Test 2

  |

  +-- New Browser

  +-- Execute

  +-- Close Browser

This provides a clean starting state for each test method.


41. Base Test with BeforeClass

@BeforeClass executes before the first test method in a class. It can be used when a browser session is intentionally shared across test methods, although this should be designed carefully because shared state can reduce test independence.

@BeforeClass

public void setUpClass() {

    driver = new ChromeDriver();

}

For most independent Selenium tests, @BeforeMethod and @AfterMethod provide clearer isolation.


42. BeforeMethod vs BeforeClass

Feature@BeforeMethod@BeforeClass
ExecutionBefore each test methodBefore the first test method in a class
Browser isolationBetter for independent testsMay share browser state
Common useFresh browser setupClass-level setup
Cleanup pairing@AfterMethod@AfterClass


43. Base Test with @BeforeSuite

@BeforeSuite executes before the entire TestNG suite. It is more appropriate for suite-level initialization than browser creation.

@BeforeSuite

public void beforeSuite() {

    System.out.println(

        "Starting automation suite"

    );

}

For example, suite-level setup could initialize shared configuration or logging.


44. What Should Not Be Put in BaseTest?

BaseTest should contain common framework behavior rather than every possible automation operation.

Avoid placing the following unnecessarily inside BaseTest:

  • Every application's page-specific locators.
  • Login-specific business logic.
  • Search-specific actions.
  • Checkout-specific operations.
  • Large amounts of test data.
  • Every assertion from every test.
  • Unrelated utility functions.

These responsibilities should be moved into Page Objects, test classes, utilities, Data Providers, or dedicated framework components.


45. Base Test Responsibility

ResponsibilitySuitable Location
WebDriver lifecycleBaseTest / DriverFactory
Browser creationDriverFactory
Page locatorsPage Classes
Test scenarioTest Classes
Test dataDataProvider / Test Data utilities
ConfigurationConfigReader
ReportsReporting utility / Listener
ScreenshotsScreenshot utility / Listener
LoggingLogger utility


46. Complete Base Test Example

import org.openqa.selenium.WebDriver;

import org.openqa.selenium.chrome.ChromeDriver;

import org.testng.annotations.AfterMethod;

import org.testng.annotations.BeforeMethod;

 

public class BaseTest {

 

    protected WebDriver driver;

 

    @BeforeMethod(alwaysRun = true)

    public void setUp() {

 

        driver = new ChromeDriver();

 

        driver.manage()

              .window()

              .maximize();

 

        driver.get(

            "https://example.com"

        );

    }

 

    @AfterMethod(alwaysRun = true)

    public void tearDown() {

 

        if (driver != null) {

            driver.quit();

        }

    }

}


47. Complete Test Class Using BaseTest

import org.testng.Assert;

import org.testng.annotations.Test;

 

public class HomePageTest extends BaseTest {

 

    @Test

    public void verifyHomePageTitle() {

 

        String title =

            driver.getTitle();

 

        Assert.assertTrue(

            title.length() > 0,

            "Page title should not be empty"

        );

    }

 

    @Test

    public void verifyHomePageUrl() {

 

        String url =

            driver.getCurrentUrl();

 

        Assert.assertTrue(

            url.contains("example.com"),

            "URL should contain expected domain"

        );

    }

}


48. Base Test with POM Complete Flow

BaseTest

    |

    +-- Creates WebDriver

    |

    +-- Opens Application

    |

    v

LoginTest

    |

    v

LoginPage

    |

    +-- Enter Username

    +-- Enter Password

    +-- Click Login

    |

    v

DashboardPage

    |

    +-- Verify Dashboard

    |

    v

BaseTest

    |

    +-- Close WebDriver


49. Recommended Project Structure

src

|-- test

|   |-- java

|       |-- base

|       |   |-- BaseTest.java

|       |

|       |-- pages

|       |   |-- LoginPage.java

|       |   |-- HomePage.java

|       |   |-- DashboardPage.java

|       |

|       |-- tests

|       |   |-- LoginTest.java

|       |   |-- SearchTest.java

|       |   |-- CheckoutTest.java

|       |

|       |-- utilities

|       |   |-- DriverFactory.java

|       |   |-- ConfigReader.java

|       |   |-- WaitUtils.java

|       |   |-- ScreenshotUtils.java

|       |

|       |-- listeners

|           |-- TestListener.java

|

|-- resources

|   |-- config.properties

|   |-- testdata

|

|-- testng.xml

|-- pom.xml


50. Base Test in a Real Automation Framework

In a larger framework, BaseTest acts as one layer of the overall architecture rather than containing every framework feature.

                 TestNG

                    |

                    v

                BaseTest

                    |

          +---------+---------+

          |         |         |

          v         v         v

      Driver     Config    Listener

      Factory    Reader

          |

          v

      WebDriver

          |

          v

      Page Objects

          |

          v

      Test Classes

          |

          v

      Assertions

          |

          v

      Reports


51. Base Test with Maven

BaseTest works normally when Selenium and TestNG are managed through Maven.

mvn test

The Maven build can execute TestNG tests, while BaseTest automatically performs the required browser setup and cleanup.


52. Base Test in CI/CD

BaseTest is particularly useful in CI/CD because browser initialization and cleanup can be standardized for every automated test.

Developer Commit

       |

       v

CI/CD Pipeline

       |

       v

Maven Build

       |

       v

TestNG

       |

       v

BaseTest

       |

       v

WebDriver

       |

       v

Test Execution

       |

       v

Reports / Screenshots

Environment-specific values such as browser, base URL, headless mode, or remote execution settings can be supplied through configuration or pipeline parameters.


53. Base Test and Selenium Grid

When Selenium Grid or another remote WebDriver service is used, BaseTest or DriverFactory can create a remote WebDriver instead of a local browser.

BaseTest

    |

    v

DriverFactory

    |

    +-- Local Chrome

    |

    +-- Local Firefox

    |

    +-- Remote Chrome

    |

    +-- Remote Firefox

    |

    v

WebDriver

This allows the test classes to remain mostly independent of how the browser is created.


54. Base Test with Remote WebDriver

URL gridUrl =

    new URL("http://localhost:4444");

 

ChromeOptions options =

    new ChromeOptions();

 

driver =

    new RemoteWebDriver(

        gridUrl,

        options

    );

The exact Grid URL and capabilities depend on the Selenium Grid or remote browser infrastructure being used.


55. Common Mistakes in BaseTest

  • Creating a new WebDriver inside every test method.
  • Forgetting to close the browser.
  • Using driver.close() when the intention is to end the complete session.
  • Making the driver inaccessible to child classes.
  • Putting too much application-specific logic into BaseTest.
  • Sharing a single driver unsafely during parallel execution.
  • Hard-coding environment configuration everywhere.
  • Creating duplicate browser initialization logic.
  • Mixing page locators with browser lifecycle code.
  • Putting large amounts of test data inside BaseTest.


56. Common Mistake: Duplicate Driver Creation

A common mistake is creating another WebDriver inside the test class even though BaseTest already provides one.

Incorrect:

public class LoginTest extends BaseTest {

 

    @Test

    public void loginTest() {

 

        WebDriver driver =

            new ChromeDriver();

 

        driver.get(

            "https://example.com"

        );

    }

}

Preferred:

public class LoginTest extends BaseTest {

 

    @Test

    public void loginTest() {

 

        driver.get(

            "https://example.com"

        );

    }

}


57. Common Mistake: Forgetting Teardown

If the browser is not closed after execution, multiple browser sessions can remain open and consume system resources.

Use a cleanup method:

@AfterMethod(alwaysRun = true)

public void tearDown() {

 

    if (driver != null) {

        driver.quit();

    }

}


58. Common Mistake: Shared Driver in Parallel Tests

Using a single shared WebDriver instance for multiple parallel test threads can result in one test interacting with the browser state of another test.

For parallel execution, use an appropriate driver-management strategy such as ThreadLocal.

Thread 1 -> Driver 1

Thread 2 -> Driver 2

Thread 3 -> Driver 3


59. Best Practices for BaseTest

  • Keep BaseTest focused on common test infrastructure.
  • Use protected or controlled WebDriver access.
  • Use @BeforeMethod and @AfterMethod when independent browser sessions are desired.
  • Always clean up WebDriver resources.
  • Move browser creation into DriverFactory for larger frameworks.
  • Keep environment settings in configuration files.
  • Use Page Objects for page-specific operations.
  • Use Data Providers for data-driven tests.
  • Use listeners for reporting and screenshots when appropriate.
  • Use ThreadLocal for suitable parallel execution designs.
  • Avoid putting business logic into BaseTest.
  • Keep test classes focused on test scenarios and assertions.
  • Use meaningful method and class names.
  • Keep the framework modular.


60. BaseTest vs Test Class

BaseTestTest Class
Common framework setupSpecific test scenario
WebDriver lifecycleTest actions
Browser configurationAssertions
Common cleanupBusiness validation
Reusable functionalityScenario-specific logic


61. BaseTest vs Page Class

BaseTestPage Class
Manages test environmentRepresents a web page
Creates WebDriverStores page locators
Handles setup and teardownContains page actions
Common to many testsSpecific to a page/component
Does not normally contain page locatorsContains page locators


62. BaseTest vs Utility Class

BaseTestUtility Class
Test lifecycleReusable helper operation
WebDriver setupConfiguration reading
WebDriver cleanupScreenshot handling
Test environment coordinationWait/helper functions


63. Practical Project Example

Consider a Selenium automation framework for an e-commerce application.

BaseTest

    |

    +-- Start Chrome

    +-- Maximize Window

    +-- Open Application

    +-- Close Browser

          |

          v

LoginTest

    |

    +-- Login

          |

          v

SearchTest

    |

    +-- Search Product

          |

          v

ProductTest

    |

    +-- Verify Product

          |

          v

CheckoutTest

    |

    +-- Complete Checkout

All tests reuse the browser lifecycle supplied by BaseTest.


64. Complete Practical Framework Example

public class BaseTest {

 

    protected WebDriver driver;

 

    @BeforeMethod(alwaysRun = true)

    public void setUp() {

 

        driver = new ChromeDriver();

 

        driver.manage()

              .window()

              .maximize();

 

        driver.get(

            "https://example.com"

        );

    }

 

    @AfterMethod(alwaysRun = true)

    public void tearDown() {

 

        if (driver != null) {

            driver.quit();

        }

    }

}

public class LoginTest extends BaseTest {

 

    @Test

    public void validLoginTest() {

 

        LoginPage loginPage =

            new LoginPage(driver);

 

        loginPage.login(

            "testuser",

            "password"

        );

 

        Assert.assertTrue(

            driver.getTitle()

                  .contains("Dashboard")

        );

    }

}


65. Base Test Architecture

                    BaseTest

                       |

          +------------+------------+

          |            |            |

          v            v            v

       Driver       Config       Lifecycle

       Factory      Reader       Methods

          |            |            |

          +------------+------------+

                       |

                       v

                  WebDriver

                       |

                       v

                 Page Objects

                       |

                       v

                  Test Classes

                       |

                       v

                  Assertions

                       |

                       v

              Reports / Screenshots


66. Base Test Learning Roadmap

  1. Understand Java inheritance.
  2. Learn Selenium WebDriver basics.
  3. Learn TestNG annotations.
  4. Understand @BeforeMethod and @AfterMethod.
  5. Create a basic BaseTest class.
  6. Extend BaseTest from test classes.
  7. Use protected WebDriver.
  8. Add browser configuration.
  9. Add application URL configuration.
  10. Introduce DriverFactory.
  11. Add ConfigReader.
  12. Integrate Page Object Model.
  13. Add Data Providers.
  14. Add screenshot and reporting utilities.
  15. Learn parallel execution and ThreadLocal.
  16. Integrate Maven and CI/CD.
  17. Build a complete reusable Selenium automation framework.


67. Practical Exercises

  1. Create a BaseTest class using ChromeDriver.
  2. Add @BeforeMethod for browser setup.
  3. Add @AfterMethod for browser cleanup.
  4. Create a LoginTest extending BaseTest.
  5. Create a SearchTest extending BaseTest.
  6. Move the application URL into a configuration file.
  7. Create a DriverFactory for Chrome and Firefox.
  8. Add browser selection using TestNG parameters.
  9. Create a LoginPage using Page Object Model.
  10. Use BaseTest with a DataProvider.
  11. Add screenshot capture for failed tests.
  12. Implement ThreadLocal WebDriver for parallel execution.
  13. Integrate the framework with Maven.
  14. Execute the framework through a CI/CD pipeline.


68. Interview Questions on BaseTest

1. What is BaseTest?

BaseTest is a reusable parent class that contains common automation setup and teardown functionality used by multiple test classes.

2. Why is BaseTest used in Selenium?

It reduces duplicate WebDriver setup and cleanup code and provides a consistent test lifecycle.

3. Which TestNG annotations are commonly used in BaseTest?

@BeforeMethod and @AfterMethod are commonly used for per-test browser setup and cleanup. Other lifecycle annotations can also be used depending on the framework design.

4. Why is WebDriver commonly protected?

Protected access allows child test classes to use the WebDriver inherited from BaseTest.

5. Why use driver.quit() in BaseTest?

driver.quit() ends the WebDriver session and closes the associated browser windows.

6. Can BaseTest be used with Page Object Model?

Yes. BaseTest can provide the WebDriver while Page Object classes manage page-specific locators and actions.

7. Can BaseTest support multiple browsers?

Yes. Browser selection can be implemented using TestNG parameters, configuration, and a DriverFactory.

8. Can BaseTest support parallel execution?

Yes. For parallel execution, driver management must be thread-safe. ThreadLocal WebDriver is one common approach.

9. Should page locators be stored in BaseTest?

Generally no. Page locators should be maintained inside the corresponding Page Object classes.

10. Should test data be stored in BaseTest?

Generally no. Test data should be managed through Data Providers, external files, databases, or dedicated test-data utilities.

11. What is the difference between BaseTest and DriverFactory?

BaseTest manages test lifecycle and framework setup, while DriverFactory focuses on creating WebDriver instances.

12. What is the advantage of BaseTest in a large framework?

It provides a centralized and reusable foundation for common test infrastructure.

13. Can BaseTest use TestNG parameters?

Yes. Browser, environment, headless mode, and other configuration values can be supplied through TestNG parameters.

14. Why should BaseTest not contain business logic?

Keeping business logic outside BaseTest maintains separation of responsibilities and makes the framework easier to maintain.

15. How can BaseTest support screenshots?

BaseTest can expose the WebDriver to a screenshot utility or listener that captures screenshots during failures.

16. How can BaseTest support reporting?

Reporting can be integrated through TestNG listeners or dedicated reporting utilities that observe test execution results.

17. What happens if BaseTest does not close WebDriver?

Browser sessions may remain open and consume system resources, potentially affecting later tests and the execution environment.

18. Why is test independence important?

Independent tests reduce dependencies on previous test state and make failures easier to reproduce and diagnose.

19. Can BaseTest be abstract?

Yes. An abstract BaseTest can be used when it is intended only as a parent class and should not itself be instantiated as a test class.

20. What is the main purpose of BaseTest?

The main purpose is to centralize reusable test infrastructure such as WebDriver lifecycle management while keeping individual test classes focused on test scenarios.


69. Quick Reference Table

ConceptPurpose
BaseTestReusable parent test class
WebDriverControls the browser
@BeforeMethodRuns setup before a test method
@AfterMethodRuns cleanup after a test method
protected driverAllows child tests to access WebDriver
DriverFactoryCentralizes WebDriver creation
ConfigReaderReads framework configuration
Page ObjectStores page locators and actions
DataProviderSupplies test data
ListenerMonitors test execution events
ThreadLocalProvides thread-specific driver storage


70. Summary

BaseTest is an important architectural component of a Selenium TestNG automation framework. It centralizes common test setup and teardown operations so that individual test classes do not need to duplicate WebDriver initialization and browser cleanup.

A typical BaseTest uses TestNG lifecycle annotations such as @BeforeMethod and @AfterMethod. The WebDriver is commonly exposed to child test classes through protected access or a controlled getter method.

For larger automation frameworks, BaseTest can work together with DriverFactory, ConfigReader, Page Object Model, Data Providers, TestNG listeners, screenshot utilities, reporting tools, Maven, Selenium Grid, and CI/CD pipelines.

The most important design principle is to keep BaseTest focused on reusable framework infrastructure. Page-specific actions should remain in Page Objects, test scenarios should remain in test classes, and test data should remain in dedicated data sources or Data Providers.


71. Course Resources

Learn more about Selenium automation, TestNG, Page Object Model, and framework development:

Final Takeaway: A well-designed BaseTest provides a reusable foundation for Selenium automation by centralizing WebDriver lifecycle management, browser configuration, and common test infrastructure while allowing individual test classes and Page Objects to remain clean, focused, and maintainable.

whatsapp